using System;
using System.Collections.Generic;
using System.Text;
using ACS.Compiler.Synthes;
using ACS.Compiler.Tables;
using ACS.Compiler.Tables.Modes;
using ACS.Compiler.Tree.Interfaces;
using ACS.Compiler.Util;

namespace ACS.Compiler.Tree.Impl
{
    public class Assign : Statement
    {
        private IExpression _dest;
        private IExpression _source;

        public override void MatchSelect(Select select)
        {
            MatchExpression(select);
        }

        public override void MatchExpression(IExpression expression)
        {
            if (_dest == null)
            {
                _dest = expression;
            } else
            {
                _source = expression;
            }  
        }

        public override void MatchCall(Call call)
        {
            MatchExpression(call);
        }

        public override void MatchIdent(Ident ident)
        {
            MatchExpression(ident);
        }
        public override Statements StatementType
        {
            get { return Statements.Assign; }
        }

        public override void Resolve(string ns, DataTable localData)
        {
            Mode destMode = null;
            Mode srcMode = null;
            switch (_dest.ExpressionType)
            {
                case Expression.Expressions.Select:
                case Expression.Expressions.Slice:
                case Expression.Expressions.Ident:
                    destMode = ((IFinalIdent)_dest).ResolveIdent(ns, localData, null);
                    break;
                default:
                    Logger.Instance.TraceError("wrong assignment dest.", this);
                    break;
            }
            srcMode = _source.ModeResolveExpression(ns, localData, null);      
            if (!ModesTable.Castable(srcMode, destMode))
            {
                Logger.Instance.TraceModesNotEquals(destMode, srcMode, this);
            }
        }

        public override void Format()
        {
            Formatter.Current.Format(String.Format("{0}.Assign({1});", Dest.ToDeclareString(), Source.ToDeclareString()));
        }


        public IExpression Dest
        {
            get { return _dest; }
        }

        public IExpression Source
        {
            get { return _source; }
        }
    }
}
